import { Form, FormProps } from 'antd';
import { ClassConstructor, ClassMirror } from '@quick-toolkit/class-mirror';
import { PropsWithChildren } from 'react';
import { FeatureFormItem } from '../feature-form-item';
import { FeatureFormContext } from './context.ts';
import { ApiRequestDecorate } from '@quick-toolkit/http';
import { useSubmit } from 'react-router-dom';
import { HTMLFormMethod } from '@remix-run/router';
import { SubmitTarget } from 'react-router-dom/dist/dom';
import { transformer } from '../../utils';
import { FeatureFormList } from 'src/feature-antd/feature-form-list';

export function formBuilder<T extends object>(type: ClassConstructor<T>) {
  const classMirror = ClassMirror.reflect(type);
  const decorates = classMirror.getAllDecorates(ApiRequestDecorate);
  const mirrors = classMirror.getAllProperties();

  let action = '';
  let method = '';

  decorates.reverse().forEach((o) => {
    action = o.metadata.url;
    method = o.metadata.method;
  });

  function IForm<T extends object>(props: PropsWithChildren<FormProps<T>>) {
    const { action, method, onFinish, ...rest } = props;
    const submit = useSubmit();
    return (
      <Form<T>
        action={action}
        method={method}
        onFinish={(value: T) => {
          const data = transformer.transform(type, value) as Record<
            string,
            unknown
          >;
          if (onFinish) {
            return onFinish(data as T);
          }
          submit(data as SubmitTarget, {
            method: method as HTMLFormMethod,
            encType: 'application/json',
          });
        }}
        {...rest}
      />
    );
  }

  function Element(props: PropsWithChildren<FormProps<T>>) {
    return (
      <FeatureFormContext.Provider value={mirrors}>
        <IForm
          action={action}
          method={method}
          autoComplete="off"
          autoCapitalize="off"
          autoCorrect="off"
          autoSave="off"
          {...props}
        />
      </FeatureFormContext.Provider>
    );
  }
  return {
    Form: Element,
    Item: FeatureFormItem<T>,
    List: FeatureFormList<T>,
    action,
    method,
    allDecorates: decorates,
    allProperties: mirrors,
  };
}
